/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.food.zoom;

import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

public abstract class VersionedGestureDetector {
	private static final String TAG = "VersionedGestureDetector";

	OnGestureListener mListener;
	static Context _context;

	public static VersionedGestureDetector newInstance(Context context, OnGestureListener listener) {
		_context = context;
		final int sdkVersion = Build.VERSION.SDK_INT;
		VersionedGestureDetector detector = null;
		/*
        if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
            detector = new CupcakeDetector();
        } else */ 

		if (sdkVersion < Build.VERSION_CODES.FROYO) {
			detector = new EclairDetector();
		} else {
			detector = new FroyoDetector(context);
		}

		Log.d(TAG, "Created new " + detector.getClass());
		detector.mListener = listener;

		return detector;
	}

	public abstract boolean onTouchEvent(MotionEvent ev);

	public interface OnGestureListener {
		public void onDrag(float dx, float dy);
		public void onScale(float scaleFactor);
		public void onAnyClick(float dx, float dy);
		public void onActionUp(float dx, float dy);
	}

	private static class CupcakeDetector extends VersionedGestureDetector {
		float mLastTouchX;
		float mLastTouchY;

		float getActiveX(MotionEvent ev) {
			return ev.getX();
		}

		float getActiveY(MotionEvent ev) {
			return ev.getY();
		}

		boolean shouldDrag() {
			return true;
		}

		@Override
		public boolean onTouchEvent(MotionEvent ev) {
			switch (ev.getAction()) {
			case MotionEvent.ACTION_DOWN: {
				mLastTouchX = getActiveX(ev);
				mLastTouchY = getActiveY(ev);
				mListener.onAnyClick(mLastTouchX, mLastTouchY);
				break;
			}
			case MotionEvent.ACTION_MOVE: {
				final float x = getActiveX(ev);
				final float y = getActiveY(ev);

				if (shouldDrag()) {
					mListener.onDrag(x - mLastTouchX, y - mLastTouchY);
				}

				mLastTouchX = x;
				mLastTouchY = y;
				break;
			}
			case MotionEvent.ACTION_UP:
				mListener.onActionUp(ev.getX(), ev.getY());
				break;
			}
			return true;
		}
	}

	private static class EclairDetector extends CupcakeDetector {
		private static final int INVALID_POINTER_ID = -1;
		@SuppressWarnings("unused")
		private int mActivePointerId = INVALID_POINTER_ID;
		private int mActivePointerIndex = 0;

		@Override
		float getActiveX(MotionEvent ev) {
			return ev.getX(mActivePointerIndex);
		}

		@Override
		float getActiveY(MotionEvent ev) {
			return ev.getY(mActivePointerIndex);
		}

		@Override
		public boolean onTouchEvent(MotionEvent ev) {
			final int action = ev.getAction();
			switch (action & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				mActivePointerId = ev.getPointerId(0);
				mListener.onAnyClick(ev.getX(), ev.getY());
				return true;
			case MotionEvent.ACTION_CANCEL:            
				mActivePointerId = INVALID_POINTER_ID;
				return true;
			case MotionEvent.ACTION_UP:
				mActivePointerId = INVALID_POINTER_ID;
				mListener.onActionUp(ev.getX(), ev.getY());
				return true;
			case MotionEvent.ACTION_POINTER_DOWN:            	
				final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)  >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
		if (pointerIndex < ev.getPointerCount() && ev.getPointerCount() > 0){
			mLastTouchX = ev.getX(pointerIndex);
			mLastTouchY = ev.getY(pointerIndex);
			mListener.onAnyClick(mLastTouchX, mLastTouchY);	            		            
		}
		return true;
		case MotionEvent.ACTION_POINTER_UP:
			final int pointerIndex2 = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)  >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
			if (pointerIndex2 < ev.getPointerCount() && ev.getPointerCount() > 0){
				mLastTouchX = ev.getX(pointerIndex2);
				mLastTouchY = ev.getY(pointerIndex2);
				mListener.onActionUp(mLastTouchX, mLastTouchY);	            
			}
			return true;                
		default:
			return super.onTouchEvent(ev);
			}                       
		}
	}

	private static class FroyoDetector extends EclairDetector {
		private ScaleGestureDetector mDetector;

		public FroyoDetector(Context context) {
			mDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
				@Override public boolean onScale(ScaleGestureDetector detector) {
					mListener.onScale(detector.getScaleFactor());
					return true;
				}
			});
		}

		@Override
		boolean shouldDrag() {
			return !mDetector.isInProgress();
		}

		@Override
		public boolean onTouchEvent(MotionEvent ev) {
			mDetector.onTouchEvent(ev);
			return super.onTouchEvent(ev);
		}
	}
}
